package com.game.league.service;

import com.game.base.server.crud.CRUDMgr;
import com.game.base.utils.log.Logger;
import com.game.base.utils.toast.ToastUtil;
import com.game.base.view.dialog.DialogUtils;
import com.game.league.articles.exchange.Exchange;
import com.game.league.articles.table.Articles;
import com.game.league.articles.table.Banner;
import com.game.league.entrance.config.Config;
import com.game.league.entrance.user.UserMgr;
import com.game.league.entrance.user.table.User;
import com.game.league.mine.table.FlowBill;
import com.game.league.task.table.MyTask;
import com.game.league.task.table.Task;

import java.util.List;

import cn.bmob.v3.BmobObject;
import cn.bmob.v3.BmobQuery;
import cn.bmob.v3.datatype.BmobPointer;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.FindListener;
import cn.bmob.v3.listener.QueryListener;
import cn.bmob.v3.listener.SaveListener;
import cn.bmob.v3.listener.UpdateListener;

/**
 * 统一接口管理类
 * <p>
 * 1: 缓存策略[http://doc.bmob.cn/data/android/develop_doc/#_29]
 * 2: 数据查询[http://doc.bmob.cn/data/android/develop_doc/#4]
 * <p>
 * Created by Su on 2019/5/28.
 */
public class InterfaceMgr {
    private static volatile InterfaceMgr interfaceMgr;

    public synchronized static InterfaceMgr getInstance() {
        if (interfaceMgr == null) {
            synchronized (InterfaceMgr.class) {
                if (interfaceMgr == null) {
                    interfaceMgr = new InterfaceMgr();
                }
            }
        }
        return interfaceMgr;
    }

    // ================================  缓存策略 ====================================

    /**
     * 只从网络获取数据，且不会将数据缓存在本地，这是默认的缓存策略。
     */
    private void cacheIgnore(BmobQuery<? extends BmobObject> query) {
        query.setCachePolicy(BmobQuery.CachePolicy.IGNORE_CACHE);
    }

    /**
     * 只从缓存读取数据，如果缓存没有数据会导致一个BmobException,可以忽略不处理这个BmobException.
     */
    private void cacheOnly(BmobQuery<? extends BmobObject> query) {
        query.setCachePolicy(BmobQuery.CachePolicy.CACHE_ONLY);
    }

    /**
     * 只从网络获取数据，同时会在本地缓存数据。
     */
    private void netOnly(BmobQuery<? extends BmobObject> query) {
        query.setCachePolicy(BmobQuery.CachePolicy.NETWORK_ONLY);
    }

    /**
     * 先从网络读取数据，如果没有，再从缓存中获取。
     */
    private void netElseCache(BmobQuery<? extends BmobObject> query) {
        query.setCachePolicy(BmobQuery.CachePolicy.NETWORK_ELSE_CACHE);
    }

    /**
     * 先从缓存读取数据，如果没有，再从网络获取。
     */
    private void cacheElseNet(BmobQuery<? extends BmobObject> query) {
        query.setCachePolicy(BmobQuery.CachePolicy.CACHE_ELSE_NETWORK);
    }

    /**
     * 先从缓存取数据，无论结果如何都会再次从网络获取数据。也就是说会产生2次调用。
     */
    private void cacheThenNet(BmobQuery<? extends BmobObject> query) {
        query.setCachePolicy(BmobQuery.CachePolicy.CACHE_THEN_NETWORK);
    }


    // ================================  接口 ====================================
    public static Config serverConfig;      // 在线配置

    public static Config getConfig() {
        if (serverConfig == null) {
            serverConfig = new Config();
            serverConfig.setSignReward(1f); // 设置默认值
        }
        return serverConfig;
    }

    /**
     * 获取在线配置
     */
    public void getServerConfig() {
        BmobQuery<Config> query = new BmobQuery<>();
        netElseCache(query);
        query.findObjects(new FindListener<Config>() {
            @Override
            public void done(List<Config> list, BmobException e) {
                if (e != null || list == null || list.isEmpty()) return;
                serverConfig = list.get(0);
                Logger.d("在线配置获取成功");
            }
        });
    }

    /**
     * 获取广告轮播
     */
    public void getBannerList(int type, FindListener<Banner> listener) {
        BmobQuery<Banner> query = new BmobQuery<>();
        netElseCache(query);
        query.addWhereEqualTo("isOpen", true)
                .addWhereEqualTo("type", type)
                .findObjects(listener);
    }

    /**
     * 获取物品列表
     */
    public void getArticlesList(int type, FindListener<Articles> listener) {
        BmobQuery<Articles> query = new BmobQuery<>();
        netElseCache(query);
        query.setLimit(1000)
                .addWhereEqualTo("type", type)
                .addWhereEqualTo("isOpen", true)
                .order("-updatedAt")
                .findObjects(listener);
    }

    /**
     * 兑换物品
     */
    public void exchangeArticles(Articles articles, int num, SaveListener<String> listener) {
        Exchange exchange = new Exchange();
        exchange.setUser(UserMgr.getCurrentUser());
        exchange.setArticles(articles);
        exchange.setNum(num);
        CRUDMgr.getInstance().saveSingle(exchange, listener);
    }

    /**
     * 删除某条兑换记录
     */
    public void deleteExchangeArticles(String objectId) {
        Exchange exchange = new Exchange();
        exchange.setObjectId(objectId);
        CRUDMgr.getInstance().delete(exchange);
    }

    /**
     * 获取我的已兑换物品
     */
    public void getMyExchangeArticles(FindListener<Exchange> listener) {
        BmobQuery<Exchange> query = new BmobQuery<>();
        netElseCache(query);
        query.addWhereEqualTo("user", new BmobPointer(UserMgr.getCurrentUser()))
                .include("articles")  //包含物品信息
                .order("-createdAt")
                .findObjects(listener);
    }

    /**
     * 获取任务列表
     */
    public void getTaskList(int type, FindListener<Task> listener) {
        BmobQuery<Task> query = new BmobQuery<>();
        netElseCache(query);
        query.addWhereEqualTo("type", type)
                .addWhereEqualTo("open", true)
                .order("-order")
                .findObjects(listener);
    }

    /**
     * 申请任务
     *
     * @param objectId 任务ID
     */
    public void applyTask(String objectId, UpdateListener listener) {
        BmobQuery<Task> query = new BmobQuery<>();
        cacheIgnore(query);
        query.getObject(objectId, new QueryListener<Task>() {
            @Override
            public void done(Task task, BmobException e) {
                if (e == null) {
                    if (task.getRemainNum() <= 0) {
                        DialogUtils.closeTipDialog();
                        ToastUtil.showShort("任务已经被抢光啦！");
                        return;
                    }

                    task.setRemainNum(task.getRemainNum() - 1);
                    if (task.getRemainNum() <= 0 && !task.isManyDays()) {  // 多天的持续性任务，不自动下线
                        task.setOpen(false);
                    }
                    task.update(objectId, listener);
                } else {
                    DialogUtils.closeTipDialog();
                    ToastUtil.showShort("访问异常，请稍后重试");
                }
            }
        });
    }

    /**
     * 释放任务数量
     */
    public void resetRobTaskNum(String objectId) {
        BmobQuery<Task> query = new BmobQuery<>();
        cacheIgnore(query);
        query.getObject(objectId, new QueryListener<Task>() {
            @Override
            public void done(Task task, BmobException e) {
                if (e == null) {
                    task.setRemainNum(task.getRemainNum() + 1);
                    if (task.getRemainNum() == 1) {  // 管理员将物品下线后，由用户操作使其再次上线的Bug
                        task.setOpen(true);
                    }
                    task.update(objectId, new UpdateListener() {
                        @Override
                        public void done(BmobException e) {
                        }
                    });
                }
            }
        });
    }

    /**
     * 提交任务
     */
    public void submitTask(MyTask myTask, SaveListener<String> listener) {
        myTask.setUser(UserMgr.getCurrentUser());
        CRUDMgr.getInstance().saveSingle(myTask, listener);
    }

    /**
     * 获取我的提交任务
     */
    public void getMyTaskList(FindListener<MyTask> listener) {
        BmobQuery<MyTask> query = new BmobQuery<>();
        netElseCache(query);
        query.addWhereEqualTo("user", new BmobPointer(UserMgr.getCurrentUser()))
                .include("task")
                .order("status,-createdAt")
                .findObjects(listener);
    }

    /**
     * 更新收支明细记录
     */
    public void setFlowBillList(User user, String title, float price, boolean isAdd, SaveListener<String> listener) {
        FlowBill flowBill = new FlowBill();
        flowBill.setUser(user);
        flowBill.setTitle(title);
        flowBill.setCurrentCoin(user.getCoinRemain());
        flowBill.setPrice(price);
        flowBill.setAdd(isAdd);
        CRUDMgr.getInstance().saveSingle(flowBill, listener);
    }

    /**
     * 获取收支明细记录
     */
    public void getFlowBillList(FindListener<FlowBill> listener) {
        BmobQuery<FlowBill> query = new BmobQuery<>();
        netElseCache(query);
        query.addWhereEqualTo("user", new BmobPointer(UserMgr.getCurrentUser()))
                .order("-updatedAt")
                .findObjects(listener);
    }
}
